home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / dogmove.c < prev    next >
C/C++ Source or Header  |  1992-12-05  |  18KB  |  658 lines

  1. /*    SCCS Id: @(#)dogmove.c    3.1    92/11/26    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #include "mfndpos.h"
  8. #include "edog.h"
  9.  
  10. #ifdef OVL0
  11.  
  12. static boolean FDECL(dog_hunger,(struct monst *,struct edog *));
  13. static boolean FDECL(dog_invent,(struct monst *,struct edog *,int));
  14. static int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int));
  15.  
  16. #ifndef MUSE
  17. #define DROPPABLES(mtmp) mtmp->minvent
  18. #else
  19. static struct obj *FDECL(DROPPABLES, (struct monst *));
  20.  
  21. static struct obj *
  22. DROPPABLES(mon)
  23. register struct monst *mon;
  24. {
  25.     register struct obj *obj;
  26.     struct obj *wep = MON_WEP(mon);
  27.  
  28.     for(obj = mon->minvent; obj; obj = obj->nobj)
  29.         if (!obj->owornmask && obj != wep) return obj;
  30.     return (struct obj *)0;
  31. }
  32. #endif
  33.  
  34. static const char NEARDATA nofetch[] = { BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, 0 };
  35.  
  36. #endif /* OVL0 */
  37.  
  38. STATIC_VAR xchar gtyp, gx, gy;    /* type and position of dog's current goal */
  39.  
  40. STATIC_DCL void FDECL(dog_eat, (struct monst *, struct obj *, int, int));
  41. STATIC_PTR void FDECL(wantdoor, (int, int, genericptr_t));
  42.  
  43. #ifdef OVLB
  44.  
  45. STATIC_OVL void
  46. dog_eat(mtmp, obj, x, y)
  47. register struct monst *mtmp;
  48. register struct obj * obj;
  49. int x, y;
  50. {
  51.     register struct edog *edog = EDOG(mtmp);
  52.     int nutrit;
  53.  
  54.     if(edog->hungrytime < moves)
  55.         edog->hungrytime = moves;
  56.     /*
  57.      * It is arbitrary that the pet takes the same length of time to eat
  58.      * as a human, but gets more nutritional value.
  59.      */
  60.     if (obj->oclass == FOOD_CLASS) {
  61.         if(obj->otyp == CORPSE) {
  62.         mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6);
  63.         nutrit = mons[obj->corpsenm].cnutrit;
  64.         } else {
  65.         mtmp->meating = objects[obj->otyp].oc_delay;
  66.         nutrit = objects[obj->otyp].oc_nutrition;
  67.         }
  68.         switch(mtmp->data->msize) {
  69.         case MZ_TINY: nutrit *= 8; break;
  70.         case MZ_SMALL: nutrit *= 6; break;
  71.         default:
  72.         case MZ_MEDIUM: nutrit *= 5; break;
  73.         case MZ_LARGE: nutrit *= 4; break;
  74.         case MZ_HUGE: nutrit *= 3; break;
  75.         case MZ_GIGANTIC: nutrit *= 2; break;
  76.         }
  77.         if(obj->oeaten) {
  78.         mtmp->meating = eaten_stat(mtmp->meating, obj);
  79.         nutrit = eaten_stat(nutrit, obj);
  80.         }
  81.     } else if (obj->oclass == GOLD_CLASS) {
  82.         mtmp->meating = ((int)obj->quan/2000) + 1;
  83.         nutrit = ((int)obj->quan/20);
  84.     } else {
  85.         /* Unusual pet such as gelatinous cube eating odd stuff.
  86.          * meating made consistent with wild monsters in mon.c.
  87.          * nutrit made consistent with polymorphed player nutrit in
  88.          * eat.c.  (This also applies to pets eating gold.)
  89.          */
  90.         mtmp->meating = obj->owt/20 + 1;
  91.         nutrit = 5*objects[obj->otyp].oc_nutrition;
  92.     }
  93.     edog->hungrytime += nutrit;
  94.     mtmp->mconf = 0;
  95.     if (mtmp->mtame < 20) mtmp->mtame++;
  96.     if(cansee(x,y))
  97.         pline("%s eats %s.", Monnam(mtmp), (obj->oclass==FOOD_CLASS)
  98.         ? singular(obj, doname) : doname(obj));
  99.     /* It's a reward if it's DOGFOOD and the player dropped/threw it. */
  100.     /* We know the player had it if invlet is set -dlc */
  101.     if(dogfood(mtmp,obj) == DOGFOOD && obj->invlet)
  102. #ifdef LINT
  103.         edog->apport = 0;
  104. #else
  105.         edog->apport += (unsigned)(200L/
  106.         ((long)edog->dropdist+moves-edog->droptime));
  107. #endif
  108.     if (obj == uball) {
  109.         unpunish();
  110.         delobj(obj);
  111.     } else if (obj == uchain)
  112.         unpunish();
  113.     else if (obj->quan > 1L && obj->oclass == FOOD_CLASS)
  114.         obj->quan--;
  115.     else
  116.         delobj(obj);
  117. }
  118.  
  119. #endif /* OVLB */
  120. #ifdef OVL0
  121.  
  122. /* hunger effects -- returns TRUE on starvation */
  123. static boolean
  124. dog_hunger(mtmp, edog)
  125. register struct monst *mtmp;
  126. register struct edog *edog;
  127. {
  128.     if(moves > edog->hungrytime + 500) {
  129.         if(!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
  130.         edog->hungrytime = moves + 500;
  131.         /* but not too high; it might polymorph */
  132.         } else if (!mtmp->mconf) {
  133.         mtmp->mconf = 1;
  134.         mtmp->mhpmax /= 3;
  135.         if(mtmp->mhp > mtmp->mhpmax)
  136.             mtmp->mhp = mtmp->mhpmax;
  137.         if(mtmp->mhp < 1) goto dog_died;
  138.         if(cansee(mtmp->mx, mtmp->my))
  139.             pline("%s is confused from hunger.", Monnam(mtmp));
  140.         else {
  141.             char buf[BUFSZ];
  142.  
  143.             Strcpy(buf, "the ");
  144.             You("feel worried about %s.", mtmp->mnamelth ?
  145.             NAME(mtmp) : strcat(buf, Hallucination
  146.             ? rndmonnam() : mtmp->data->mname));
  147.         }
  148.         } else if(moves > edog->hungrytime + 750 || mtmp->mhp < 1) {
  149.         dog_died:
  150. #ifdef WALKIES
  151.         if(mtmp->mleashed)
  152.             Your("leash goes slack.");
  153. #endif
  154.         if(cansee(mtmp->mx, mtmp->my))
  155.             pline("%s dies%s.", Monnam(mtmp),
  156.                 (mtmp->mhp >= 1) ? "" : " from hunger");
  157.         else
  158.             You("have a sad feeling for a moment, then it passes.");
  159.         mondied(mtmp);
  160.         return(TRUE);
  161.         }
  162.     }
  163.     return(FALSE);
  164. }
  165.  
  166. /* do something with object (drop, pick up, eat) at current position
  167.  * returns TRUE if object eaten (since that counts as dog's move)
  168.  */
  169. static boolean
  170. dog_invent(mtmp, edog, udist)
  171. register struct monst *mtmp;
  172. register struct edog *edog;
  173. int udist;
  174. {
  175.     register int omx, omy;
  176.     struct obj *obj;
  177.  
  178.     omx = mtmp->mx;
  179.     omy = mtmp->my;
  180.  
  181.     /* if we are carrying sth then we drop it (perhaps near @) */
  182.     /* Note: if apport == 1 then our behaviour is independent of udist */
  183.     if(DROPPABLES(mtmp) || mtmp->mgold) {
  184.         if(!rn2(udist) || !rn2((int) edog->apport))
  185.         if(rn2(10) < edog->apport){
  186.             relobj(mtmp, (int)mtmp->minvis, TRUE);
  187.             if(edog->apport > 1) edog->apport--;
  188.             edog->dropdist = udist;        /* hpscdi!jon */
  189.             edog->droptime = moves;
  190.         }
  191.     } else {
  192.         if((obj=level.objects[omx][omy]) && !index(nofetch,obj->oclass)
  193. #ifdef MAIL
  194.             && obj->otyp != SCR_MAIL
  195. #endif
  196.                                     ){
  197.         if (dogfood(mtmp, obj) <= CADAVER) {
  198.             dog_eat(mtmp, obj, omx, omy);
  199.             return TRUE;
  200.         }
  201.         if(can_carry(mtmp, obj) && !obj->cursed)
  202.             if(rn2(20) < edog->apport+3)
  203.             if(rn2(udist) || !rn2((int) edog->apport)) {
  204.                 if (cansee(omx, omy) && flags.verbose)
  205.                 pline("%s picks up %s.", Monnam(mtmp),
  206.                     distant_name(obj, doname));
  207.                 freeobj(obj);
  208.                 newsym(omx,omy);
  209.                 mpickobj(mtmp,obj);
  210.             }
  211.         }
  212.     }
  213.     return FALSE;
  214. }
  215.  
  216. /* set dog's goal -- gtyp, gx, gy
  217.  * returns -1/0/1 (dog's desire to approach player) or -2 (abort move)
  218.  */
  219. static int
  220. dog_goal(mtmp, edog, after, udist, whappr)
  221. register struct monst *mtmp;
  222. struct edog *edog;
  223. int after, udist, whappr;
  224. {
  225.     register int omx, omy;
  226.     boolean in_masters_sight;
  227.     register struct obj *obj;
  228.     xchar otyp;
  229.     int appr;
  230.  
  231.     omx = mtmp->mx;
  232.     omy = mtmp->my;
  233.  
  234.     in_masters_sight = couldsee(omx, omy);
  235.  
  236.     if (!edog
  237. #ifdef WALKIES
  238.             || mtmp->mleashed    /* he's not going anywhere... */
  239. #endif
  240.                     ) {
  241.         gtyp = APPORT;
  242.         gx = u.ux;
  243.         gy = u.uy;
  244.     } else {
  245. #define DDIST(x,y) (dist2(x,y,omx,omy))
  246. #define SQSRCHRADIUS 5
  247.         int min_x, max_x, min_y, max_y;
  248.         register int nx, ny;
  249.  
  250.         gtyp = UNDEF;    /* no goal as yet */
  251.         gx = gy = 0;    /* suppress 'used before set' message */
  252.  
  253.         if ((min_x = omx - SQSRCHRADIUS) < 0) min_x = 0;
  254.         if ((max_x = omx + SQSRCHRADIUS) >= COLNO) max_x = COLNO - 1;
  255.         if ((min_y = omy - SQSRCHRADIUS) < 0) min_y = 0;
  256.         if ((max_y = omy + SQSRCHRADIUS) >= ROWNO) max_y = ROWNO - 1;
  257.  
  258.         /* nearby food is the first choice, then other objects */
  259.         for (obj = fobj; obj; obj = obj->nobj) {
  260.         nx = obj->ox;
  261.         ny = obj->oy;
  262.         if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) {
  263.             otyp = dogfood(mtmp, obj);
  264.             if (otyp > gtyp || otyp == UNDEF)
  265.             continue;
  266.             if (otyp < MANFOOD) {
  267.             if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) {
  268.                 gx = nx;
  269.                 gy = ny;
  270.                 gtyp = otyp;
  271.             }
  272.             } else if(gtyp == UNDEF && in_masters_sight &&
  273.                   !mtmp->minvent &&
  274.                   (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) &&
  275.                   (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) &&
  276.                   edog->apport > rn2(8) &&
  277.                   can_carry(mtmp,obj)) {
  278.             gx = nx;
  279.             gy = ny;
  280.             gtyp = APPORT;
  281.             }
  282.         }
  283.         }
  284.     }
  285.  
  286.     /* follow player if appropriate */
  287.     if (gtyp == UNDEF ||
  288.         (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)) {
  289.         gx = u.ux;
  290.         gy = u.uy;
  291.         if (after && udist <= 4 && gx == u.ux && gy == u.uy)
  292.             return(-2);
  293.         appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
  294.         if (udist > 1) {
  295.             if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
  296.                whappr ||
  297.                (mtmp->minvent && rn2((int) edog->apport)))
  298.                 appr = 1;
  299.         }
  300.         /* if you have dog food it'll follow you more closely */
  301.         if (appr == 0) {
  302.             obj = invent;
  303.             while (obj) {
  304.                 if(dogfood(mtmp, obj) == DOGFOOD) {
  305.                     appr = 1;
  306.                     break;
  307.                 }
  308.                 obj = obj->nobj;
  309.             }
  310.         }
  311.     } else
  312.         appr = 1;    /* gtyp != UNDEF */
  313.     if(mtmp->mconf)
  314.         appr = 0;
  315.  
  316. #define FARAWAY (COLNO + 2)        /* position outside screen */
  317.     if (gx == u.ux && gy == u.uy && !in_masters_sight) {
  318.         register coord *cp;
  319.  
  320.         cp = gettrack(omx,omy);
  321.         if (cp) {
  322.         gx = cp->x;
  323.         gy = cp->y;
  324.         if(edog) edog->ogoal.x = 0;
  325.         } else {
  326.         /* assume master hasn't moved far, and reuse previous goal */
  327.         if(edog && edog->ogoal.x &&
  328.            ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) {
  329.             gx = edog->ogoal.x;
  330.             gy = edog->ogoal.y;
  331.             edog->ogoal.x = 0;
  332.         } else {
  333.             int fardist = FARAWAY * FARAWAY;
  334.             gx = gy = FARAWAY; /* random */
  335.             do_clear_area(omx, omy, 9, wantdoor,
  336.                   (genericptr_t)&fardist);
  337.  
  338.             /* here gx == FARAWAY e.g. when dog is in a vault */
  339.             if (gx == FARAWAY || (gx == omx && gy == omy)) {
  340.             gx = u.ux;
  341.             gy = u.uy;
  342.             } else if(edog) {
  343.             edog->ogoal.x = gx;
  344.             edog->ogoal.y = gy;
  345.             }
  346.         }
  347.         }
  348.     } else if(edog) {
  349.         edog->ogoal.x = 0;
  350.     }
  351.     return appr;
  352. }
  353.  
  354. /* return 0 (no move), 1 (move) or 2 (dead) */
  355. int
  356. dog_move(mtmp, after)
  357. register struct monst *mtmp;
  358. register int after;    /* this is extra fast monster movement */
  359. {
  360.     int omx, omy;        /* original mtmp position */
  361.     int appr, whappr, udist;
  362.     int i, j;
  363.     register struct edog *edog = EDOG(mtmp);
  364.     struct obj *obj = (struct obj *) 0;
  365.     xchar otyp;
  366.     boolean has_edog, cursemsg = FALSE, do_eat = FALSE;
  367.     xchar nix, niy;        /* position mtmp is (considering) moving to */
  368.     register int nx, ny;    /* temporary coordinates */
  369.     xchar cnt, uncursedcnt, chcnt;
  370.     int chi = -1, nidist, ndist;
  371.     coord poss[9];
  372.     long info[9], allowflags;
  373. #define GDIST(x,y) (dist2(x,y,gx,gy))
  374.  
  375.     /*
  376.      * Tame Angels have isminion set and an ispriest structure instead of
  377.      * an edog structure.  Fortunately, guardian Angels need not worry
  378.      * about mundane things like eating and fetching objects, and can
  379.      * spend all their energy defending the player.  (They are the only
  380.      * monsters with other structures that can be tame.)
  381.      */
  382.     has_edog = !mtmp->isminion;
  383.  
  384.     omx = mtmp->mx;
  385.     omy = mtmp->my;
  386.     if (has_edog && dog_hunger(mtmp, edog)) return(2);    /* starved */
  387.  
  388.     udist = distu(omx,omy);
  389.     /* maybe we tamed him while being swallowed --jgm */
  390.     if (!udist) return(0);
  391.  
  392.     nix = omx;    /* set before newdogpos */
  393.     niy = omy;
  394.  
  395.     if (has_edog && dog_invent(mtmp, edog, udist))    /* eating something */
  396.         goto newdogpos;
  397.  
  398.     if (has_edog)
  399.         whappr = (moves - edog->whistletime < 5);
  400.     else
  401.         whappr = 0;
  402.  
  403.     appr = dog_goal(mtmp, has_edog ? edog : (struct edog *)0,
  404.                             after, udist, whappr);
  405.     if (appr == -2) return(0);
  406.  
  407.     allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
  408.     if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
  409.     if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
  410.     if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
  411.         allowflags |= ALLOW_U;
  412.         if (!has_edog) {
  413.         coord mm;
  414.         /* Guardian angel refuses to be conflicted; rather,
  415.          * it disappears, angrily, and sends in some nasties
  416.          */
  417.         if (canseemon(mtmp) || sensemon(mtmp)) {
  418.             pline("%s rebukes you, saying:", Monnam(mtmp));
  419.             verbalize("Since you desire conflict, have some more!");
  420.         }
  421.         mongone(mtmp);
  422.         i = rnd(4);
  423.         while(i--) {
  424.             mm.x = u.ux;
  425.             mm.y = u.uy;
  426.             if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
  427.             (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,
  428.                      mm.x, mm.y, FALSE);
  429.         }
  430.         return(2);
  431.  
  432.         }
  433.     }
  434.     if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
  435.         allowflags |= OPENDOOR;
  436.         if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR;
  437.     }
  438.     if (is_giant(mtmp->data)) allowflags |= BUSTDOOR;
  439.     if (tunnels(mtmp->data) && !needspick(mtmp->data))
  440.         allowflags |= ALLOW_DIG;
  441.     cnt = mfndpos(mtmp, poss, info, allowflags);
  442.  
  443.     /* Normally dogs don't step on cursed items, but if they have no
  444.      * other choice they will.  This requires checking ahead of time
  445.      * to see how many cursed item squares are around.
  446.      */
  447.     uncursedcnt = 0;
  448.     for (i = 0; i < cnt; i++) {
  449.         nx = poss[i].x; ny = poss[i].y;
  450.         if (MON_AT(nx,ny)) continue;
  451.         for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere)
  452.             if (obj->cursed) goto skipu;
  453.         uncursedcnt++;
  454. skipu:;
  455.     }
  456.  
  457.     chcnt = 0;
  458.     chi = -1;
  459.     nidist = GDIST(nix,niy);
  460.  
  461.     for (i = 0; i < cnt; i++) {
  462.         nx = poss[i].x;
  463.         ny = poss[i].y;
  464. #ifdef WALKIES
  465.         /* if leashed, we drag him along. */
  466.         if (mtmp->mleashed && distu(nx, ny) > 4) continue;
  467. #endif
  468.         /* if a guardian, try to stay close by choice */
  469.         if (!has_edog &&
  470.             (j = distu(nx, ny)) > 16 && j >= udist) continue;
  471.  
  472.         if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) {
  473.             int stat;
  474.             register struct monst *mtmp2 = m_at(nx,ny);
  475.  
  476.             if ((int)mtmp2->m_lev >= (int)mtmp->m_lev+2 ||
  477.             (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10) &&
  478.              mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
  479.              && (perceives(mtmp->data) || !mtmp2->minvis)) ||
  480.             (mtmp2->data==&mons[PM_GELATINOUS_CUBE] && rn2(10)) ||
  481.             (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp) ||
  482.             (mtmp->mhp*4 < mtmp->mhpmax &&
  483.              mtmp2->mpeaceful && !Conflict) ||
  484.                (mtmp2->data->mlet == S_COCKATRICE &&
  485.                 !resists_ston(mtmp->data)))
  486.             continue;
  487.  
  488.             if (after) return(0); /* hit only once each move */
  489.  
  490.             stat = mattackm(mtmp, mtmp2);
  491.  
  492.             /* aggressor (pet) died */
  493.             if (stat & MM_AGR_DIED) return 2;
  494.  
  495.             if ((stat & MM_HIT) && !(stat & MM_DEF_DIED) &&
  496.             rn2(4) && mtmp2->mlstmv != monstermoves) {
  497.             stat = mattackm(mtmp2, mtmp);    /* return attack */
  498.             if (stat & MM_DEF_DIED) return 2;
  499.             }
  500.  
  501.             return 0;
  502.         }
  503.  
  504.         {   /* dog avoids traps, but perhaps it has to pass a trap
  505.              * in order to follow player
  506.              */
  507.             struct trap *trap;
  508.  
  509.             if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))) {
  510.             if ((trap->ttyp == RUST_TRAP
  511.                     && mtmp->data != &mons[PM_IRON_GOLEM])
  512.                 || trap->ttyp == STATUE_TRAP
  513.                 || ((trap->ttyp == PIT
  514.                     || trap->ttyp == SPIKED_PIT
  515.                     || (trap->ttyp == TRAPDOOR &&
  516.                     !Can_fall_thru(&u.uz)))
  517.                     && (is_flyer(mtmp->data) ||
  518.                     is_clinger(mtmp->data)))
  519.                 || (trap->ttyp == SLP_GAS_TRAP &&
  520.                     resists_sleep(mtmp->data)))
  521.                 if(!trap->tseen || rn2(3)) continue;
  522. #ifdef WALKIES
  523.             if (!mtmp->mleashed) {
  524. #endif
  525.                 if (!trap->tseen && rn2(40)) continue;
  526.                 if (rn2(10)) continue;
  527. #ifdef WALKIES
  528.             }
  529. # ifdef SOUNDS
  530.             else if (flags.soundok)
  531.                 whimper(mtmp);
  532. # endif
  533. #endif
  534.             }
  535.         }
  536.  
  537.         /* dog eschews cursed objects, but likes dog food */
  538.         for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
  539.             if (obj->cursed && !mtmp->mleashed && uncursedcnt)
  540.             goto nxti;
  541.             if (obj->cursed) cursemsg = TRUE;
  542.             if (has_edog && (otyp = dogfood(mtmp, obj)) < MANFOOD &&
  543.                 (otyp < ACCFOOD || edog->hungrytime <= moves)){
  544.             /* Note: our dog likes the food so much that he
  545.              * might eat it even when it conceals a cursed object */
  546.             nix = nx;
  547.             niy = ny;
  548.             chi = i;
  549.             do_eat = TRUE;
  550.             goto newdogpos;
  551.             }
  552.         }
  553.  
  554.         for (j = 0; j < MTSZ && j < cnt-1; j++)
  555.             if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
  556.                 if (rn2(4*(cnt-j))) goto nxti;
  557.  
  558.         j = ((ndist = GDIST(nx,ny)) - nidist) * appr;
  559.         if ((j == 0 && !rn2(++chcnt)) || j < 0 ||
  560.             (j > 0 && !whappr &&
  561.                 ((omx == nix && omy == niy && !rn2(3))
  562.                     || !rn2(12))
  563.             )) {
  564.             nix = nx;
  565.             niy = ny;
  566.             nidist = ndist;
  567.             if(j < 0) chcnt = 0;
  568.             chi = i;
  569.         }
  570.     nxti:    ;
  571.     }
  572. newdogpos:
  573.     if (nix != omx || niy != omy) {
  574.         if (info[chi] & ALLOW_U) {
  575. #ifdef WALKIES
  576.             if (mtmp->mleashed) { /* play it safe */
  577.                 pline("%s breaks loose of %s leash!",
  578.                     Monnam(mtmp),
  579.                     humanoid(mtmp->data)
  580.                         ? (mtmp->female ? "her" : "his")
  581.                         : "its");
  582.                 m_unleash(mtmp);
  583.             }
  584. #endif
  585.             (void) mattacku(mtmp);
  586.             return(0);
  587.         }
  588.         /* insert a worm_move() if worms ever begin to eat things */
  589.         remove_monster(omx, omy);
  590.         place_monster(mtmp, nix, niy);
  591.         if (cursemsg && (cansee(omx,omy) || cansee(nix,niy)))
  592.             pline("%s moves only reluctantly.", Monnam(mtmp));
  593.         for (j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
  594.         mtmp->mtrack[0].x = omx;
  595.         mtmp->mtrack[0].y = omy;
  596.         /* We have to know if the pet's gonna do a combined eat and
  597.          * move before moving it, but it can't eat until after being
  598.          * moved.  Thus the do_eat flag.
  599.          */
  600.         if (do_eat)
  601.             dog_eat(mtmp, obj, nix, niy);
  602.     }
  603. #ifdef WALKIES
  604.       /* an incredible kludge, but the only way to keep pooch near
  605.        * after it spends time eating or in a trap, etc.
  606.        */
  607.       else if (mtmp->mleashed && distu(omx, omy) > 4) {
  608.         coord cc;
  609.  
  610.         nx = sgn(omx - u.ux);
  611.         ny = sgn(omy - u.uy);
  612.         cc.x = u.ux + nx;
  613.         cc.y = u.uy + ny;
  614.         if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext;
  615.  
  616.          i  = xytod(nx, ny);
  617.         for (j = (i + 7)%8; j < (i + 1)%8; j++) {
  618.             dtoxy(&cc, j);
  619.             if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext;
  620.         }
  621.         for (j = (i + 6)%8; j < (i + 2)%8; j++) {
  622.             dtoxy(&cc, j);
  623.             if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext;
  624.         }
  625.         cc.x = mtmp->mx;
  626.         cc.y = mtmp->my;
  627. dognext:
  628.         remove_monster(mtmp->mx, mtmp->my);
  629.         place_monster(mtmp, cc.x, cc.y);
  630.         newsym(cc.x,cc.y);
  631.         set_apparxy(mtmp);
  632.     }
  633. #endif
  634.     return(1);
  635. }
  636.  
  637. #endif /* OVL0 */
  638. #ifdef OVLB
  639.  
  640. /*ARGSUSED*/    /* do_clear_area client */
  641. STATIC_PTR void
  642. wantdoor(x, y, distance)
  643. int x, y;
  644. genericptr_t distance;
  645. {
  646.     register ndist;
  647.  
  648.     if (*(int*)distance > (ndist = distu(x, y))) {
  649.     gx = x;
  650.     gy = y;
  651.     *(int*)distance = ndist;
  652.     }
  653. }
  654.  
  655. #endif /* OVLB */
  656.  
  657. /*dogmove.c*/
  658.